Convex and alpha hulls are wonderful alternatives for visualising species distributions. Here, we will show you how to create these spatial polygons using different types of data from the ALA.
The ability to visualise and predict where a species resides is important in conservation ecology. Convex hulls and alpha hulls are two ways to plot the spatial distribution of a particular species and quantify IUCN metrics. Typically, convex and alpha hulls are used when dealing with data deficient species in conservation research.
Alpha hulls have helped researchers monitor dynamic changes in species distributions. For example, distributions can shrink or expand due to habitat loss or in response to changing climate. Dr. Takach and their team used alpha hulls to investigate how distributions of Australian tropical savanna mammals have changed over time. They found that the Black-Footed Tree Rat Mesembriomys gouldii experienced contemporary range contractions. We’ve shown this below in the map we made using {galah} to access ALA data!
Figure 1: A Black-Footed Tree Rat perched on a branch by Colin Trainor CC-BY-NC 4.0](https://images.ala.org.au/image/a197988c-5da5-4260-8f2a-5bb55b468fce)
More recently, Dr. Marsh and colleagues used alpha hulls to estimate the impact the 2020 mega bushfires had on invertebrates in southern Australia. Since invertebrate data is inherently sparse, alpha hulls are really useful when you only have a handful of records to work with.
In this post, we’ll explain the difference between convex hulls and alpha hulls and show you how to create them using different data types! We will actually be using an invertebrate species from Dr. Marsh’s study in the walk-through below.
First we will install/load the R packages we’ll need:
# install.packages("pacman")
pacman::p_load(remotes, galah, tidyverse, alphahull, sp, sf, ozmaps, patchwork)
We will use occurrence records of an endemic damselfly, Austroargiolestes calcaris, commonly known as the Powdered Flatwing to illustrate the various spatial polygons you can make
Now let’s use galah to download occurrence records from the Atlas of Living Australia. Note that you will need to first set up your own ALA configuration locally using galah_config before fetching records.
#Download Powdered flatwing records
galah_call() |>
galah_identify("Austroargiolestes calcaris") |>
galah_filter(profile="ALA") |>
galah_select(group = "basic") |>
atlas_occurrences() -> dfly
Before we can plot anything, we need to remove all duplicated values and any NA values!
# De-duplication
dfly |>
filter(! duplicated(decimalLongitude) & ! duplicated(decimalLatitude)) |> #Remove duplicates
filter(! is.na(decimalLongitude) & ! is.na(decimalLatitude) ) -> dfly_clean # Exclude NA in coordinates
Put simply, a convex hull is a way to draw around all the points of a species on a map with as few lines as possible. It’s defined as the smallest polygon that encloses all the points in the data set
To plot a convex hull on a map:
chull() to compute a convex hull from our cleaned Powdered Flatwing data.{ozmaps} package and set it a specific coordinate system.# Compute convex hull
dfly_clean |>
select(decimalLongitude, decimalLatitude) |>
chull() -> dfly_chull
# Create hull outline
dfly_chull_pts <- c(dfly_chull, dfly_chull[1])
# Map of Australia
aus <- st_transform(ozmaps::ozmap_country, 4326)
# Plot occurrences and convex hull
ggplot() +
geom_sf(data = aus, colour = "black", fill = "white") +
geom_point(data = dfly_clean, aes(decimalLongitude, decimalLatitude), colour = "black", size = 0.8) +
geom_polygon(data = dfly_clean[dfly_chull_pts, ], aes(decimalLongitude, decimalLatitude), fill = "orange", colour = "black", alpha = 0.5) +
coord_sf(xlim=c(142, 152),ylim=c(-32,-44)) +
labs(title = "Convex hull", x = "Longtitude (DD)", y = "Latitude (DD)") + ## DD here stands for decimal degrees
theme_bw() -> dfly_chull_p
dfly_chull_p
Alpha hulls have concave arced edges. They have an alpha parameter that controls the level of detail, or how tightly the boundary fits around the point set. The arched edges allow the shape to fit around the occurrence records more tightly.
To illustrate, here are three alpha hulls with increasing values for alpha:
Notice as the alpha value increases, the more simplified and fewer arches the alpha hull becomes. Alpha = 2 is what we’ve most commonly come across in research, and is the value recommended by the IUCN for various forms of species vulnerability analysis, but choose your alpha values according to your needs.
Citizen science data are often excluded from scientific analyses due to poor data quality e.g. rare species can be misidentified by a lay person. Below, we show you how you can plot your alpha hulls using all records vs. a subset of data without citizen science records.
To make our alpha hulls, we will rely on an R package hull2spatial developed by Cecina Babich Morrow. Check out their blog post about the package. This package allows us to convert ahull objects into ggplot-friendly objects. You can install the package using:
remotes::install_github("babichmorrowc/hull2spatial")
The below workflow is going to produce the same plot as a = 2 above.
To make and plot an alpha hull:
sf object.sp objectsp object into an sf object and set our coordinates project system# Turn data into a `sf` object
dfly_clean |>
st_as_sf(coords = c("decimalLongitude", "decimalLatitude"), crs = 4326) -> dfly_sf
# Compute an alpha hull
dfly_clean |>
select(decimalLongitude, decimalLatitude) |>
ahull(alpha = 2) -> dfly_ahull
# Transform `ahull` into `sp` object
hull2spatial::ahull2poly(dfly_ahull) -> dfly_sp_df
# Transform `sp` into `sf` object, set coordinate system
dfly_sp_df |>
st_as_sf() |>
st_set_crs(st_crs(aus)) -> dfly_sf_ahull
# Plot the occurrences and alpha hull
ggplot() +
geom_sf(data = aus, colour = "black", fill = "white") +
geom_sf(data = dfly_sf, colour = "black", size = 0.5) +
geom_sf(data = dfly_sf_ahull, fill = "orange", alpha = 0.5) +
coord_sf(xlim=c(142, 152),ylim=c(-32,-44)) +
ggtitle("Alpha hull") +
labs(x = "Longtitude (DD)", y = "Latitude (DD)") +
theme_bw() -> dfly_ahull_p
dfly_ahull_p
Although a strict data criteria will reduce the number of data points, we can still compute and plot alpha hulls for the Powdered Flatwing - this is the beauty of them!
We are going to repeat the same steps for generating an alpha hull but with a subset of the data. The only additional step is narrowing records using galah_filter() to exclude citizen science data before the data is downloaded.
# Create a vector excluding human observations
institution_only <- c("PRESERVED_SPECIMEN", "LIVING_SPECIMEN",
"MACHINE_OBSERVATION", "MATERIAL_SAMPLE")
galah_call() |>
galah_identify("Austroargiolestes calcaris") |>
galah_filter(basisOfRecord == institution_only,
profile = "ALA") |>
galah_select(group = "basic") |>
atlas_occurrences() -> dfly_specionly
You’ll notice with this map that there are two separate hulls! This is a benefit of an alpha hull over a convex hull. The mathematical constraints of a convex hull mean all points must be contained within a single polygon - this can lead to an over-estimation of range. The map we showed you at the beginning of this post is great example of the multiple hulls.
While sophisticated tools for modelling species distribution exist, they require a substantial amounts of data to properly inform conservation research. Convex polygons and alpha hulls are flexible alternatives, particularly for understudied species, to help us understand dynamic changes to their distributions.